# @Author:黄景涛
# @Date: 2023/12/27
from copy import copy
from collections.abc import Iterable
import re
from datetime import datetime

from files_util.excel_handler import Excel
from files_util.xmind_handler import Xmind


class CaseInfo:
    """一条用例的加工，包括：标题、分组、前置步骤、步骤、预期结果"""

    def __init__(self, row):
        self.row = row[0]
        self.levels = row[1]
        self.final_data = []

    def is_title_member(self, s: str):
        """最后一个节点内容，是否是用例标题的一部分"""
        mp = ('UI交互', '功能', '场景')

        for c in s:
            if c in (',', '，', ':', '：'):
                # 倒数第二个节点名称，在mp内能找到，则取最后一个节点第一个逗号前部分作为标题
                if any(re.search(item, self.row[-2]) for item in mp):
                    title_member = self.row[-1].split('：')[0].split('，')[0].strip().lstrip('1、')
                    return title_member
                else:
                    # TODO 可扩展其他的处理结果
                    ...
                    return None
        else:
            return s

    @property
    def case_title(self):
        """加工用例标题"""

        # 处理标题前半部分
        title_header = '_'.join(self.row[-3:-1])

        # 处理标题后半部分
        title_tail = self.is_title_member(self.row[-1])

        # 拼接完整标题
        if title_tail:
            title = title_header + '_' + title_tail
        else:
            title = title_header
        print(f'标题：{title}')
        return title

    @property
    def case_level(self):
        """用例等级"""

        # xmind中，主题的标记类型，与用例等级的映射表
        mp = {'priority-1': 'P0', 'priority-2': 'P1', 'priority-3': 'P2', 'priority-4': 'P3', 'task-done': 'P2'}

        if not self.levels:
            return

        res = []
        for i in self.levels:
            if mp.get(i) is not None:
                res.append(mp.get(i))

        if not res:
            return

        res.sort()
        print(f'用例等级：{res}')
        return res[0]

    @property
    def case_group(self):
        """加工用例分组"""
        cp_row = copy(self.row)
        # 去除根节点
        cp_row.pop(0)
        # 判断：1.路径在6个节点以内，去除末尾2个节点，然后拼接为用例分组；2.路径超过6个节点，则一直去除，只保留前4个拼接为用例分组
        if len(cp_row) <= 6:
            for i in range(2):
                cp_row.pop()
        else:
            while len(cp_row) > 4:
                cp_row.pop()

        group = '/'.join(cp_row)
        # group = '/'.join(self.row[1:3])
        print(f'分组：{group}')
        return group

    @property
    def case_pre_step(self):
        """加工前置步骤"""
        pre_step = '1、\n2、'
        return pre_step

    @property
    def case_step(self):
        """加工测试步骤"""
        step = '1、\n2、\n3、'
        return step

    @property
    def case_expect(self):
        """加工预期结果"""

        # 控制是否要加序号
        flag = False

        expect = re.split('\n', self.row[-1])
        # 若预期结果有换行符，标记为True
        if len(expect) > 1:
            flag = True

        # 是否要加序号的处理
        if flag:
            mp1 = ['1、', '2、', '3、', '4、', '5、', '6、', '7、', '8、', '9、', '10、']
            mp2 = ['①', '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩']

            exp_res = []
            for idx, item in enumerate(expect, 1):
                if not any(item.strip().startswith(i) for i in (*mp1, *mp2)):
                    item = f'{idx}、{item.strip()}'
                if not item.startswith(' ') and item.strip()[0] in mp2:
                    item = f'  {item}'
                exp_res.append(item)

            exp_res = '\n'.join(exp_res)
            print(f"预期：{exp_res}")
            return exp_res

        return self.row[-1]

    @property
    def output_data(self):
        self.final_data.append(self.case_title)
        self.final_data.append(self.case_level)
        self.final_data.append(self.case_group)
        self.final_data.append(self.case_pre_step)
        self.final_data.append(self.case_step)
        self.final_data.append(self.case_expect)
        return self.final_data


def data_processing(datas: Iterable):
    """加工xmind元数据"""
    final_datas = []
    for row in datas:
        final_datas.append(CaseInfo(row).output_data)
        print('==================================================')
    return final_datas


def main(xmind_file: str):
    """xmind数据，写入excel"""
    # 1.xmind处理
    x = Xmind(xmind_file)
    xmind_datas = x.meta_data_to_list()

    # 2.数据加工
    final_datas = data_processing(xmind_datas)

    # 3.excel处理
    sheet_header = ('用例名称', '用例等级', '分组', '前置步骤', '测试步骤', '预期结果')

    time_stramp = datetime.now().strftime('%Y_%m_%d-%H%M%S')
    excel_file = f'./测试用例_{time_stramp}.xlsx'
    e = Excel(excel_file, sheet_header=sheet_header)
    # 写入表头
    e.write_header()
    # 遍历待写入的数据，写入每行
    for data in final_datas:
        e.write_row(data)
    # 保存excel
    e.save()


if __name__ == '__main__':
    main('V1.0-测试点.xmind')
